import os
import json
import time
from openai import OpenAI

# 初始化OpenAI客户端
client = OpenAI(
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    api_key="330f54b7-915b-48a9-9599-c5e47c118cb5"  # 建议改为环境变量读取：os.getenv("ARK_API_KEY")
)


def load_non_unique_cases(json_file_path: str) -> list:
    """
    读取JSON文件，筛选出解决办法不唯一的案例
    :param json_file_path: 问题唯一性判断结果JSON文件路径
    :return: 解决办法不唯一的案例列表
    """
    try:
        if not os.path.exists(json_file_path):
            raise FileNotFoundError(f"文件不存在：{json_file_path}")

        with open(json_file_path, "r", encoding="utf-8") as f:
            data = json.load(f)

        # 处理可能的错误格式（若根节点是错误信息）
        if isinstance(data, dict) and "错误" in data:
            raise ValueError(f"原始数据存在错误：{data['错误']}")

        # 筛选解决办法不唯一的案例
        non_unique_cases = [case for case in data if case.get("解决办法是否唯一") == "否"]
        print(f"共筛选出{len(non_unique_cases)}个解决办法不唯一的案例\n")
        return non_unique_cases

    except FileNotFoundError as e:
        print(f"读取文件失败：{str(e)}")
        return []
    except json.JSONDecodeError:
        print("JSON文件格式错误，无法解析")
        return []
    except Exception as e:
        print(f"筛选案例失败：{str(e)}")
        return []


def process_single_case(original_question: str) -> dict:
    """
    调用LLM处理单个不唯一案例，生成补充信息后的结果
    :param original_question: 原始用户问题
    :return: 包含补充分析和修正后问题的字典
    """
    # 构建完整提示词
    system_prompt = """
    你是拓竹科技3D打印领域的问题补充专家，需按照以下要求处理用户问题：

    一、背景：拓竹科技3D打印用户提出问题。

    二、信息补充判断标准：
    1. 需补充打印机型号：当问题涉及机型专属功能（如AMS、激光雕刻、多色混打、高温模组适配）、结构相关故障或软件适配，且未明确机型时。
    2. 需补充耗材信息：当问题涉及材料特性故障（如堵塞、变形）、适配限制（如水溶支撑）或耗材状态相关问题，且未明确耗材时。
    3. 需补充打印参数：当问题涉及打印质量问题（如层纹、拉丝），且未明确参数时。
    4. 无需补充：问题给出机型、耗材及打印参数，或问题为询问通用操作流程。

    三、处理步骤：
    1. 判定补充需求：基于上述判断标准，识别需补充的信息类型。无需补充则直接输出用户问题。
    2. 补充信息：根据用户问题和补充需求进行对应信息补充，优先选择实际3D打印场景中概率最高的组合或者与用户问题最相关的信息。
    3. 最终以拓竹科技3D打印用户的口吻将补充信息融入用户问题中，不改变用户原始问题核心意图，尽可能保留用户问题原始内容。
    4. 输出修正后问题。

    四、约束要求：
    补充信息需为拓竹产品基础信息库中内容，禁止使用库外信息：
    1. 机型库：H2S、H2D、H2D PRO、X1C、P1S、P1P、P2S、A1、A1 Mini。
    2. 耗材库：PLA、PETG、TPU、ABS、ASA、PC、ABS GF、PA6 GF、PA6 CF、ASA CF、PAHT CF 碳纤耗材、PET-CF、PPA-CF、PPS-CF。

    五、输出格式要求（严格按照此JSON格式输出，字段不可增减，内容需符合实际）：
    {
        "原始用户问题": "用户的原始问题内容",
        "补充需求分析": "详细说明需要补充的信息类型及判断依据",
        "补充信息选择": {
            "机型": "选择的机型及选择理由（若无需补充则填无）",
            "耗材": "选择的耗材及选择理由（若无需补充则填无）",
            "打印参数": "选择的打印参数及选择理由（若无需补充则填无）"
        },
        "修正后问题": "融入补充信息后的用户问题"
    }

    六、参考案例：
    {
        "原始用户问题": "该耗材与当前喷嘴不兼容",
        "补充需求分析": "问题涉及耗材与喷嘴的兼容性，属于材料特性适配限制，根据判断标准2需补充耗材信息；同时喷嘴兼容性通常与机型相关，根据判断标准1需补充机型信息。",
        "补充信息选择": {
            "机型": "X1C（高端机型，常用于测试各类耗材兼容性）",
            "耗材": "PAHT CF 碳纤耗材（碳纤维耗材对喷嘴有特殊要求，易出现兼容性问题）",
            "打印参数": "无（问题不涉及具体打印质量参数）"
    },
        "修正后问题": "我的X1C打印机使用PAHT CF碳纤耗材时，系统提示该耗材与当前喷嘴不兼容"
    }

    注意：若无需补充任何信息，补充信息选择中的三个字段均填“无”，补充需求分析说明无需补充的依据，修正后问题与原始问题一致。
    """

    try:
        response = client.chat.completions.create(
            model="deepseek-v3-1-250821",
            messages=[
                {"role": "system", "content": system_prompt.strip()},
                {"role": "user", "content": f"请处理用户问题：{original_question}"}
            ]
        )

        # 解析LLM返回的JSON结果
        response_content = response.choices[0].message.content.strip()
        processed_result = json.loads(response_content)

        # 验证输出格式的完整性
        required_fields = ["原始用户问题", "补充需求分析", "补充信息选择", "修正后问题"]
        for field in required_fields:
            if field not in processed_result:
                raise KeyError(f"缺少必要字段：{field}")

        # 验证补充信息选择的子字段
        if not isinstance(processed_result["补充信息选择"], dict):
            raise ValueError("补充信息选择字段格式错误，应为字典类型")
        info_fields = ["机型", "耗材", "打印参数"]
        for field in info_fields:
            if field not in processed_result["补充信息选择"]:
                processed_result["补充信息选择"][field] = "无"

        return processed_result

    except json.JSONDecodeError:
        return {
            "原始用户问题": original_question,
            "补充需求分析": "LLM返回格式错误，无法解析",
            "补充信息选择": {"机型": "无", "耗材": "无", "打印参数": "无"},
            "修正后问题": original_question
        }
    except KeyError as e:
        return {
            "原始用户问题": original_question,
            "补充需求分析": f"LLM返回缺少字段：{str(e)}",
            "补充信息选择": {"机型": "无", "耗材": "无", "打印参数": "无"},
            "修正后问题": original_question
        }
    except Exception as e:
        return {
            "原始用户问题": original_question,
            "补充需求分析": f"处理失败：{str(e)}",
            "补充信息选择": {"机型": "无", "耗材": "无", "打印参数": "无"},
            "修正后问题": original_question
        }


def main():
    # 配置文件路径
    input_json_path = "问题唯一性判断结果.json"
    output_json_path = "不唯一案例补充修正结果.json"

    # 步骤1：加载并筛选不唯一案例
    non_unique_cases = load_non_unique_cases(input_json_path)
    if not non_unique_cases:
        print("无可用的不唯一案例，程序终止")
        return

    # 步骤2：处理所有不唯一案例
    total_cases = len(non_unique_cases)
    total_start_time = time.time()
    final_results = []

    for idx, case in enumerate(non_unique_cases, 1):
        original_question = case.get("用户问题", "未知问题")
        print(f"正在处理第{idx}/{total_cases}个案例：{original_question}")

        start_time = time.time()
        processed = process_single_case(original_question)
        final_results.append(processed)

        elapsed_time = round(time.time() - start_time, 2)
        print(f"第{idx}个案例处理完成，耗时：{elapsed_time}秒\n")

    # 步骤3：保存结果
    total_elapsed_time = round(time.time() - total_start_time, 2)
    print(f"所有案例处理完成！总耗时：{total_elapsed_time}秒")

    with open(output_json_path, "w", encoding="utf-8") as f:
        json.dump(final_results, f, ensure_ascii=False, indent=2)

    print(f"\n结果已保存至：{output_json_path}")

    # 打印部分结果示例
    print("\n=== 处理结果示例（第一个案例）===")
    print(json.dumps(final_results[0], ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()